package co.fitstart.admin.web.controller.user;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.support.Result;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.web.resolver.Preloading;

import co.fitstart.admin.service.CourseRoundService;
import co.fitstart.admin.service.DataService;
import co.fitstart.admin.service.StudentService;
import co.fitstart.admin.service.UserAddressService;
import co.fitstart.admin.service.UserService;
import co.fitstart.admin.web.interceptor.MenuSetting;
import co.fitstart.admin.web.resolver.Secure;
import co.fitstart.entity.course.CourseType;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.user.Student;
import co.fitstart.entity.user.StudentTargetData;
import co.fitstart.entity.user.User;
import co.fitstart.entity.user.UserAddress;
import co.fitstart.entity.user.bwh.BwhRecord;
import co.fitstart.entity.user.fit.UserFit;
import co.fitstart.entity.user.inbody.InbodyRecord;
import co.fitstart.entity.user.investigation.FitInvestigation;
import co.fitstart.entity.user.investigation.HealthInvestigation;
import co.fitstart.entity.user.investigation.ParticipateInvestigation;
import co.fitstart.entity.user.profile.UserProfile;
import co.fitstart.entity.user.profile.UserRemark;
import co.fitstart.entity.user.profile.Wechat;

/**
 * 
 * @author Jack
 *
 */
@Controller
@RequestMapping("/users")
@MenuSetting("menu-user")
public class UserViewController {

    private static final Logger logger = LoggerFactory.getLogger(UserViewController.class);

    @Autowired
    @Qualifier("dataService")
    private DataService<User> userService;

    @Autowired
    private UserService currentUserService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private CourseRoundService courseRoundService;

    @Autowired
    private UserAddressService userAddressService;
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;

    /**
     * Display edit user info panel
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/edit", method = RequestMethod.GET)
    public ModelAndView editInfo(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-info-edit");

        User user = userService.load(User.class, userId);

        modelAndView.addObject("user", user);

        return modelAndView;
    }

    /**
     * Do edit user info
     * 
     * @param user
     * @param remark
     * @return
     */
    @RequestMapping(value = "/{userId}", method = RequestMethod.PATCH)
    public @ResponseBody String onEditInfo(@Preloading("userId") User user, UserRemark remark) {

        Result result = new Result();

        try {
            userService.update(user.editRemark(remark));

            result.success().message("修改基本信息成功");

        } catch (Exception e) {

            logger.error("#onEditInfo ", e);

            result.fail().message("修改基本信息失败");

        }

        return JsonUtils.toJsonString(result);
    }

    /**
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/name", method = RequestMethod.GET)
    public ModelAndView editName(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-name-edit");

        User user = userService.load(User.class, userId);

        modelAndView.addObject("user", user);

        return modelAndView;
    }

    /**
     * 
     * @param user
     * @return
     */
    @RequestMapping(value = "/{userId}/name", method = RequestMethod.PATCH)
    public @ResponseBody String onEditName(@Preloading("userId") User user) {

        Result result = new Result();

        try {

            currentUserService.editName(user);

            result.success().message("修改用户姓名成功");

        } catch (Exception e) {

            logger.error("#onEditName ", e);

            result.fail().message("修改用户姓名失败");

        }

        return JsonUtils.toJsonString(result);
    }

    /**
     * Display user profile view
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/profile", method = RequestMethod.GET)
    public ModelAndView profile(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-profile-view");

        User user = userService.load(User.class, userId);

        modelAndView.addObject("user", user);

        return modelAndView;
    }

    /**
     * Display edit user profile panel
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/profile/edit", method = RequestMethod.GET)
    public ModelAndView editProfile(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-profile-edit");

        User user = userService.load(User.class, userId);

        modelAndView.addObject(user);

        return modelAndView;
    }

    /**
     * Do edit user profile
     * 
     * @param userId
     * @param profile
     * @return
     */
    @RequestMapping(value = "/{userId}/profile", method = RequestMethod.PATCH)
    public @ResponseBody String onEditProfile(@PathVariable("userId") Long userId, UserProfile profile) {

        Result result = new Result();

        try {
            User user = userService.load(User.class, userId);

            userService.update(user.editProfile(profile));

            result.success().message("修改个人信息成功");

        } catch (Exception e) {

            logger.error("#onEditProfile ", e);

            result.fail().message("修改个人信息失败");

        }

        return JsonUtils.toJsonString(result);
    }

    /**
     * Display input info page
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/input-info", method = RequestMethod.GET)
    public ModelAndView inputInfo(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-input-info-view");

        User user = userService.load(User.class, userId);

        // 1. load healthInvestigation by student
        HealthInvestigation healthInvestigation = studentService.loadHealthInvestigation(user);
        modelAndView.addObject("healthInvestigation", healthInvestigation);

        // 2. load participateInvestigation by student
        ParticipateInvestigation participateInvestigation = studentService.loadParticipateInvestigation(user);
        modelAndView.addObject("participateInvestigation", participateInvestigation);

        modelAndView.addObject("user", user);

        return modelAndView;
    }

    /**
     * Do edit user wechat
     * 
     * @param userId
     * @param wechat
     * @return
     */
    @RequestMapping(value = "/{userId}/wechat", method = RequestMethod.PATCH)
    public @ResponseBody String onEditWechat(@PathVariable("userId") Long userId, Wechat wechat) {

        Result result = new Result();

        try {
            User user = userService.load(User.class, userId);

            userService.update(user.editWechat(wechat));

            result.success().message("修改健身数据成功");

        } catch (Exception e) {

            logger.error("#onEditWechat ", e);

            result.fail().message("修改健身数据失败");

        }

        return JsonUtils.toJsonString(result);
    }

    /**
     * Display user fit view
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/fit", method = RequestMethod.GET)
    public ModelAndView fit(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-fit-view");

        User user = userService.load(User.class, userId);

        modelAndView.addObject(user);

        return modelAndView;
    }

    /**
     * Display edit user fit panel
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/fit/edit", method = RequestMethod.GET)
    public ModelAndView editFit(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-fit-edit");

        User user = userService.load(User.class, userId);

        modelAndView.addObject(user);

        return modelAndView;
    }

    /**
     * Do edit user fit
     * 
     * @param userId
     * @param fit
     * @return
     */
    @RequestMapping(value = "/{userId}/fit", method = RequestMethod.PATCH)
    public @ResponseBody String onEditFit(@PathVariable("userId") Long userId, UserFit fit) {

        Result result = new Result();

        try {
            User user = userService.load(User.class, userId);

            userService.update(user.editFit(fit));

            result.success().message("修改健身数据成功");

        } catch (Exception e) {

            logger.error("#onEditFit ", e);

            result.fail().message("修改健身数据失败");

        }

        return JsonUtils.toJsonString(result);
    }

    /**
     * Display user inbody view
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/inbody", method = RequestMethod.GET)
    public ModelAndView inbody(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-inbody-view");

        User user = userService.load(User.class, userId);
        modelAndView.addObject(user);

        List<InbodyRecord> inbodyRecords = studentService.listInbodyRecord(user);
        modelAndView.addObject("inbodyRecords", inbodyRecords);

        return modelAndView;
    }

    /**
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/bwh", method = RequestMethod.GET)
    public ModelAndView bwhRecord(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-bwh-view");

        User user = userService.load(User.class, userId);
        modelAndView.addObject("user", user);

        List<BwhRecord> bwhRecords = studentService.listBwhRecord(user);
        modelAndView.addObject("bwhRecords", bwhRecords);

        return modelAndView;
    }

    /**
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/target-data", method = RequestMethod.GET)
    public ModelAndView targetData(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-target-data-view");

        User user = userService.load(User.class, userId);
        modelAndView.addObject("user", user);

        List<StudentTargetData> studentTargetDatas = studentService.listStudentTargetData(user);
        modelAndView.addObject("studentTargetDatas", studentTargetDatas);

        return modelAndView;
    }

    /**
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/body", method = RequestMethod.GET)
    public ModelAndView body(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-body-view");

        User user = userService.load(User.class, userId);
        // 1. list userFitRecord by student`s user
        List<FitInvestigation> fitInvestigations = studentService.listFitInvestigation(user);
        modelAndView.addObject("fitInvestigations", fitInvestigations);

        // 2. list inbodyRecords by student's user
        List<InbodyRecord> inbodyRecords = studentService.listInbodyRecord(user);
        modelAndView.addObject("inbodyRecords", inbodyRecords);

        // 3. list bwhRecords by student's user
        List<BwhRecord> bwhRecords = studentService.listBwhRecord(user);
        modelAndView.addObject("bwhRecords", bwhRecords);

        // 4. list studentTargetDatas by student's user
        List<StudentTargetData> studentTargetDatas = studentService.listStudentTargetData(user);
        modelAndView.addObject("studentTargetDatas", studentTargetDatas);

        modelAndView.addObject("user", user);

        return modelAndView;
    }

    /**
     * 
     * @param bwhId
     * @return
     */
    @RequestMapping(value = "/bwh/{bwhId}/edit", method = RequestMethod.GET)
    public ModelAndView editBwh(@PathVariable("bwhId") Long bwhId) {
        ModelAndView modelAndView = new ModelAndView("user/component/user-bwh-edit");

        modelAndView.addObject("bwhId", bwhId);

        return modelAndView;
    }

    /**
     * 
     * @param operator
     * @param bwhRecord
     * @return
     */
    @RequestMapping(value = "/bwh/{bwhId}/edit", method = RequestMethod.PATCH)
    public @ResponseBody String onEditBwh(@Secure(property = "id") Long operator,
            @Preloading("bwhId") BwhRecord bwhRecord) {
        Result result = new Result();

        try {
            studentService.editBwhRecord(bwhRecord.opeator(operator));

            result.success().message("三围数据补录成功");

        } catch (Exception e) {

            logger.error("onEditBwh() error: ", e);

            result.fail().message("三围数据补录失败");
        }

        return JsonUtils.toJsonString(result);
    }

    /**
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/course", method = RequestMethod.GET)
    public ModelAndView course(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-course-view");

        User user = userService.load(User.class, userId);
        Student student = studentService.load(user);

        List<CourseRound> courseRounds = courseRoundService.listCourseRound(student,
                new CourseType[] { CourseType.ONLINE, CourseType.INDIVIDUAL, CourseType.SPECIAL, CourseType.POSTURE, CourseType.GROUP, CourseType.YEAR });
        modelAndView.addObject("courseRounds", courseRounds);

        modelAndView.addObject("student", student);

        return modelAndView;
    }

    /**
     * 
     * @param userId
     * @return
     */
    @RequestMapping(value = "/{userId}/address", method = RequestMethod.GET)
    public ModelAndView address(@PathVariable("userId") Long userId) {

        ModelAndView modelAndView = new ModelAndView("user/component/user-address-view");

        User user = userService.load(User.class, userId);
        Student student = studentService.load(user);

        List<UserAddress> userAddresses = userAddressService.listUserAddress(user);

        modelAndView.addObject("userAddresses", userAddresses);
        modelAndView.addObject("student", student);

        return modelAndView;
    }
    
    /**
     * 
     * @param targetId
     * @return
     */
    @RequestMapping(value = "/target/{targetId}/edit", method = RequestMethod.GET)
    public ModelAndView editTarget(@PathVariable("targetId") Long targetId) {
        ModelAndView modelAndView = new ModelAndView("user/component/student-target-data-edit");

        StudentTargetData studentTargetData = genericDaoSupport.load(StudentTargetData.class, targetId);
        
        modelAndView.addObject("studentTargetData", studentTargetData);

        return modelAndView;
    }

    /**
     * 
     * @param operator
     * @param targetId
     * @param shortTarget
     * @param longTarget
     * @return
     */
    @RequestMapping(value = "/target/{targetId}/edit", method = RequestMethod.PATCH)
    public @ResponseBody String onEditTarget(@Secure(property = "id") Long operator,
                                             @PathVariable("targetId") Long targetId,
                                             @RequestParam("shortTarget") String shortTarget,
                                             @RequestParam("longTarget") String longTarget) {
        Result result = new Result();

        try {
            StudentTargetData target = genericDaoSupport.load(StudentTargetData.class, targetId);
            
            studentService.editTarget(target.edit(shortTarget, longTarget, operator));

            result.success().message("目标数据修改成功");

        } catch (Exception e) {

            logger.error("onEditUserTarget() error: ", e);

            result.fail().message("目标数据修改失败");
        }

        return JsonUtils.toJsonString(result);
    }
}
